/**
 * 
 */
package com.puneet.graphqueries.ssh;

import java.io.ByteArrayOutputStream;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

/**
 * @author puneet
 * 
 */
public class SSHExec extends SSHBase {
	private int maxwait = 4000;
	private static final String TIMEOUT_MESSAGE = "Timeout period exceeded, connection dropped.";
	/** for waiting for the command to finish */
	private Thread thread = null;
	private static final int RETRY_INTERVAL = 500;

	public void executeCommand(String host, String user, String cmd) {
		Session session = null;
		try {
			session = openSession(host, user);
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			TeeOutputStream tee = new TeeOutputStream(out, new KeepAliveOutputStream(System.out));

			final ChannelExec channel;
			session.setTimeout((int) maxwait);
			/* execute the command */
			channel = (ChannelExec) session.openChannel("exec");
			channel.setCommand(cmd);
			channel.setOutputStream(tee);
			channel.setExtOutputStream(tee);
			channel.connect();
			// wait for it to finish
			thread = new Thread() {
				public void run() {
					while (!channel.isClosed()) {
						if (thread == null) {
							return;
						}
						try {
							sleep(RETRY_INTERVAL);
						} catch (Exception e) {
							// ignored
						}
					}
				}
			};

			thread.start();
			thread.join(maxwait);

			if (thread.isAlive()) {
				// ran out of time
				thread = null;
				System.out.println(TIMEOUT_MESSAGE);

			} else {

				// this is the wrong test if the remote OS is OpenVMS,
				// but there doesn't seem to be a way to detect it.
				int ec = channel.getExitStatus();
				if (ec != 0) {
					String msg = "Remote command failed with exit status " + ec;
					System.out.println(msg);

				}
			}
		} catch (JSchException e) {
			if (e.getMessage().indexOf("session is down") >= 0) {
				System.out.println(TIMEOUT_MESSAGE);

			} else {
				System.out.println("Caught exception: " + e.getMessage());
			}
			throw new SSHException(e);
		} catch (Exception e) {
			throw new SSHException(e);
		}finally {
			if(session != null) {
				session.disconnect();
			}
		}

	}

}
